package com.keyboardr.gamerater;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Date;

import org.json.JSONException;
import org.json.JSONObject;

import android.util.Log;

public class Game implements JSONable, Serializable{
	/**
	 * 
	 */
	private static final long serialVersionUID = 8403094090990021559L;
	private static final String TAG = "Game";
	public Player winner, loser;
	private ArrayList<Player> players;
	public boolean draw;
	public Date time;
	private boolean fide;
	private double winRating, loseRating;
	
	public Game(boolean draw, Player winner, Player loser, Date time, boolean fide, ArrayList<Player> players){
		this.winner = winner;
		winRating = winner.getRating();
		this.loser = loser;
		loseRating = loser.getRating();
		this.fide = fide;
		this.time = time;
		this.draw = draw;
		this.players = players;
	}
	public Game(JSONObject jObject, ArrayList<Player> players){
		try {
			if(jObject.has("winnerIndex")){
				winner = players.get(jObject.getInt("winnerIndex"));
				loser = players.get(jObject.getInt("loserIndex"));
			}
			else{
				Player winnerJSON = new Player(jObject.getJSONObject("winner"));
				Player loserJSON = new Player(jObject.getJSONObject("loser"));
				for(int i = 0; i < players.size() && (winner == null || loser == null); i++){
					Player player = players.get(i);
					if(player.equals(winnerJSON)){
						winner = player;
					} else if (player.equals(loserJSON)){
						loser = player;
					}
				}
				if (winner == null){
					throw new NullPointerException();//This is to prevent bad data from being saved
				}
				if (loser == null){
					throw new NullPointerException();//This is to prevent bad data from being saved
				}
			}
			winRating = jObject.getDouble("winRating");
			loseRating = jObject.getDouble("loseRating");
			fide = jObject.getBoolean("fide");
			time = new Date(jObject.getLong("time"));
			draw = jObject.getBoolean("draw");
			this.players = players;
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}
	public void applyGame(){
		double expectedWinner = 1 / (1 + Math.pow(10, (loseRating - winRating)/400.0));
		double expectedLoser = 1 / (1 + Math.pow(10, (winRating - loseRating)/400.0));
		Log.d(TAG, "Expeced winner: " + expectedWinner + " loser: " + expectedLoser);
		winner.playAGame((winner.getRating() + (winner.getkFactor()*((draw?0.5:1.0) - expectedWinner) + .5)), fide);
		loser.playAGame((loser.getRating() + (loser.getkFactor()*((draw?0.5:0.0)-expectedLoser) + .5)), fide);
	}
	/**
	 * @return the winRating
	 */
	public int getWinRating() {
		return (int) winRating;
	}
	/**
	 * @return the loseRating
	 */
	public int getLoseRating() {
		return (int) loseRating;
	}
	@Override
	public JSONObject toJSON() {
		JSONObject jObject = new JSONObject();
		try {
			//jObject.put("winner", winner.toJSON());
			//jObject.put("loser", loser.toJSON());
			jObject.put("winnerIndex", players.indexOf(winner));
			jObject.put("loserIndex", players.indexOf(loser));
			jObject.put("draw", draw);
			jObject.put("time", time.getTime());
			jObject.put("fide", fide);
			jObject.put("winRating", winRating);
			jObject.put("loseRating", loseRating);
		} catch (JSONException e) {
			e.printStackTrace();
		}
		return jObject;
	}
	
}
